/**
 *  Copyright (C) 2008-2009  The Aceituna Project Team
 *  Portions of this code are Copyright(C) 2002-2007  The FreeCol Team (www.freecol.org).
 *
 *  This file is part of Aceituna Project.
 *
 *  Aceituna Project is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  Aceituna Project is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Aceituna Project.  If not, see <http://www.gnu.org/licenses/>.
 */


package com.aceitunaproject.mapdisplay;

import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import com.aceitunaproject.mapdisplay.model.Thing;
import com.aceitunaproject.mapdisplay.model.map.Map;
import com.aceitunaproject.mapdisplay.model.map.Position;
import com.aceitunaproject.mapdisplay.model.map.tile.Tile;

/**
 *
 * Classes that implement this interface are responsible for drawing the map.
 * In addition, the graphical state of the map (focus,etc) is also a responsibility of this class.
 * 
 * @author Originally from FreeCol (http://sourceforge.net/projects/freecol), modified for the Aceituna Project by Federico Bergstein
 * 
 */
public interface MapDrawer {


	
	/**
	 * Sets the map's screen size
	 * @param size
	 */
	public abstract void setSize(Dimension size);

	
	/**
	 * Gets the Thing that should be displayed on the given tile.
	 * 
	 * @param unitTile
	 *            The <code>Tile</code>.
	 * @return The <code>Thing</code> or <i>null</i> if no Thing applies.
	 */
	public abstract Thing getThingInFront(Tile thingTile);



	/**
	 * Returns the width of the map.
	 * 
	 * @return The width of the map.
	 */
	public abstract int getWidth();

	/**
	 * Returns the height of the map.
	 * 
	 * @return The height of the map.
	 */
	public abstract int getHeight();

	/**
	 * Displays the map onto the given Graphics2D.
	 * 
	 * @param g
	 *            The Graphics2D on which to display the map.
	 */
	public abstract void display(Graphics2D g);

	/**
	 * If set to <i>true</i> then a grid is drawn on the map.
	 * 
	 * @param displayGrid
	 *            <code>true</code> if the grid should be drawn on the map and
	 *            <code>false</code> otherwise.
	 */
	public abstract void setDisplayGrid(boolean displayGrid);

	

	/**
	 * Checks if the Tile at the given coordinates is displayed on the
	 * screen (or, if the map is already displayed and the focus has been
	 * changed, whether they will be displayed on the screen the next time it'll
	 * be redrawn).
	 * 
	 * @param x
	 *            The x-coordinate of the Tile in question.
	 * @param y
	 *            The y-coordinate of the Tile in question.
	 * @return 'true' if the Tile will be drawn on the screen, 'false'
	 *         otherwise.
	 */
	public abstract boolean onScreen(int x, int y);

	/**
	 * Checks if the Tile at the given coordinates is displayed on the
	 * screen (or, if the map is already displayed and the focus has been
	 * changed, whether they will be displayed on the screen the next time it'll
	 * be redrawn).
	 * 
	 * @param position
	 *            The position of the Tile in question.
	 * @return <i>true</i> if the Tile will be drawn on the screen, <i>false</i>
	 *         otherwise.
	 */
	public abstract boolean onScreen(Position position);

	/**
	 * Converts the given screen coordinates to Map coordinates. It checks to
	 * see to which Tile the given pixel 'belongs'.
	 * 
	 * @param x
	 *            The x-coordinate in pixels.
	 * @param y
	 *            The y-coordinate in pixels.
	 * @return The map coordinates of the Tile that is located at the given
	 *         position on the screen.
	 */
	public abstract Position convertToMapCoordinates(int x, int y);

	/**
	 * Returns 'true' if the Tile is near the top.
	 * 
	 * @param y
	 *            The y-coordinate of a Tile.
	 * @return 'true' if the Tile is near the top.
	 */
	public abstract boolean isMapNearTop(int y);

	/**
	 * Returns 'true' if the Tile is near the bottom.
	 * 
	 * @param y
	 *            The y-coordinate of a Tile.
	 * @return 'true' if the Tile is near the bottom.
	 */
	public abstract boolean isMapNearBottom(int y);

	/**
	 * Returns 'true' if the Tile is near the left.
	 * 
	 * @param x
	 *            The x-coordinate of a Tile.
	 * @param y
	 *            The y-coordinate of a Tile.
	 * @return 'true' if the Tile is near the left.
	 */
	public abstract boolean isMapNearLeft(int x, int y);

	/**
	 * Returns 'true' if the Tile is near the right.
	 * 
	 * @param x
	 *            The x-coordinate of a Tile.
	 * @param y
	 *            The y-coordinate of a Tile.
	 * @return 'true' if the Tile is near the right.
	 */
	public abstract boolean isMapNearRight(int x, int y);

	

	/**
	 * Gets the position of the given <code>Tile</code> on the drawn map.
	 * 
	 * @param t
	 *            The <code>Tile</code>.
	 * @return The position of the given <code>Tile</code>, or <code>null</code>
	 *         if the <code>Tile</code> is not drawn on the mapboard.
	 */
	public abstract Point getTilePosition(Tile t);

	/**
	 * Calculate the bounds of the rectangle containing a Tile on the screen,
	 * and return it. If the Tile is not on-screen a maximal rectangle is
	 * returned. The bounds includes a one-tile padding area above the Tile, to
	 * include the space needed by any units in the Tile.
	 * 
	 * @param tile
	 *            The tile on the screen.
	 * @return The bounds rectangle
	 */
	public abstract Rectangle getTileBounds(Tile tile);

	/**
	 * Calculate the bounds of the rectangle containing a Tile on the screen,
	 * and return it. If the Tile is not on-screen a maximal rectangle is
	 * returned. The bounds includes a one-tile padding area above the Tile, to
	 * include the space needed by any units in the Tile.
	 * 
	 * @param x
	 *            The x-coordinate of the Tile
	 * @param y
	 *            The y-coordinate of the Tile
	 * @return The bounds rectangle
	 */
	public abstract Rectangle getTileBounds(int x, int y);

	/**
	 * Force the next screen repaint to reposition the tiles on the window.
	 */
	public abstract void forceReposition();

	
	/**
	 * returns the height of the Tiles in the map in pixels
	 * 
	 * @return the height in pixels of the Tiles in the map.
	 */
	public abstract int getTileHeight();

	/**
	 * returns the width of the Tiles in the map in pixels
	 * 
	 * @return the width in pixels of the Tiles in the map.
	 */
	public abstract int getTileWidth();
	
	
	/**
	 * gets the Map object being drawn
	 * 
	 * @return the Map object.
	 */
	public Map getMap();

	/**
	 * Sets the focus in a given Tile
	 * @param x
	 * 		the X coordinate of the Tile
	 * @param y
	 * 		the Y coordinate of the Tile
	 */
	public abstract void setFocus(int x, int y);


	/**
	 * Highlights a tile
	 * @param posx
	 * @param posy
	 */
	public abstract void highlightTile(int posx, int posy);

}